const PENDING = 'pending' // 等待状态 初始状态
const FULFILLED = 'fulfilled' // 成功状态
const REJECTED = 'rejected' // 失败状态

class MyPromise {

  status = PENDING // 初始状态

  $value = undefined // 成功之后的值
  $reason = undefined // 失败之后的值
  successCallback = [] // 成功回调函数
  failCallback = [] // 失败回调函数


  constructor(execoter) {
    // 错误捕捉
    try {
      execoter(this.resolve, this.reject)
    } catch (error) {
      this.reject(error)
    }
    
  }

  resolve = value => { 
    if(this.status !== PENDING) {return} // 如果状态不是初始状态 等待中 那么不进行操作
    this.status = FULFILLED // 状态更改为成功
    this.$value = value // 保存成功后的值
    while(this.successCallback.length) this.successCallback.shift()() // 如果成功回调存在 那么就进行调用
  }
  reject = reason => { 
    if(this.status !== PENDING) {return} // 如果状态不是初始状态 等待中 那么不进行操作
    this.status = REJECTED // 状态更改为失败
    this.$reason = reason // 保存失败后的原因
    while(this.failCallback.length) this.failCallback.shift()() // 如果失败回调存在 那么就进行调用
  }

  then(successCallback, failCallback) { // 返回 MyPromise
    successCallback = successCallback ? successCallback : value => value // 判断回调函数是否有参数  如果没有 返回上一个参数
    failCallback = failCallback ? failCallback : reason => reason
    let promise2 = new MyPromise((resolve, reject) => { // 返回一个新的promise
      if (this.status === FULFILLED) { // 如果状态为失败
        common(promise2 ,s, resolve, reject, successCallback, this.$value)
      } else if (this.status === REJECTED) { // 如果状态为成功
        common(promise2 ,s, resolve, reject, failCallback, this.$reason)
      } else { 
        // 如果是异步函数 将成功回调和失败回调存起来
        this.successCallback.push(() => common(promise2 ,s, resolve, reject, successCallback, this.$value))
        this.failCallback.push(() => common(promise2 ,s, resolve, reject, failCallback, this.$reason))
      }
    })
    return promise2
  }

  finally(callback) { 
    return this.then(
      val => MyPromise.resolve(callback()).then(() => val),
      err => MyPromise.resolve(callback()).then(() => { throw err })
    )
  }

  catch(failCallback) { 
    return this.then(undefined, failCallback)
  }

  static all(array) { 
    let result = [] // 结果
    let index = 0 //存储一个数

    return new MyPromise((resolve, reject) => { 
      function addData(key, val) { 
        result[key] = val  // 储存进对应值
        // 这里 创建index 每次addData 后 index ++ 
        index++
        if (index === array.length) { 
        // 这里为什么这么做 是因为 如果有异步函数, 那么需要等待异步函数结束后才能 调用成功函数 
        // 而 forx循环是瞬间执行并不会等待异步函数 而array[i].then是处理了异步函数的
        // then异步函数结束后 会调用 reslove 也就是 addData(i, val)
        // 当 异步函数结束后 addData调用 index++ array内所有执行完后 调用成功函数
          resolve(result)
        }
      }
      for (let i = 0; i < array.length; i++) { 
        let current = array[i];
        if (current instanceof MyPromise) { // MyPromise 对象
          // 这里执行 这个myPromise
          current.then(val => addData(i, val), reject) // 如果是成功的回调函数 那么就存储进result 如果是失败的回调函数 那么直接 调用返回失败
        } else {
          addData(i, current) // 普通值 添加进结果里
        }
      }
    })
  }

  static resolve(val) { // 直接返回成功状态
    if (val instanceof MyPromise) { // 如果为MyPromise 那么直接返回值
      return val
    }
    return new MyPromise(resolve => resolve(val)) // 如果为普通值 那么创建一个新的MyPromise 返回
  }

}

function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) { // 判断 返回的值是否就是当前值
    return reject(new TypeError('chaining cycle detected for promise #<MyPromise>')) // 返回类型错误
  }
  if (x instanceof MyPromise) { // 判断是否是 MyPromise 是 就给对应事件传递对应参数
    // x.then(value => resolve(value), reason => reject(reason))
    x.then(resolve, reject)
  } else { 
    resolve(x)
  }
}

function common(promise2, s, resolve, reject, callback, value) { 
  setTimeout(() => { // 异步 方便获得 promise2 因为是在内部 
    try { // 错误捕捉
      let s = callback(value)
      resolvePromise(promise2 ,s, resolve, reject) 
    } catch (error) {
      reject(error)
    }
  }, 0)
}

module.exports = MyPromise